package com.dupt.system.service.impl;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson2.JSON;
import com.dupt.common.config.DUPTConfig;
import com.dupt.common.utils.DateUtils;
import com.dupt.common.utils.DictUtils;
import com.dupt.common.utils.SecurityUtils;
import com.dupt.common.utils.StringUtils;
import com.dupt.common.utils.file.FileUploadUtils;
import com.dupt.common.utils.file.FileUtils;
import com.dupt.system.domain.vo.FileInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.dupt.system.mapper.FileInfoMapper;
import com.dupt.system.domain.FileInfo;
import com.dupt.system.service.IFileInfoService;
import org.springframework.web.multipart.MultipartFile;

/**
 * 文件信息Service业务层处理
 * 
 * @author zhuanyu.sun
 * @date 2025-11-02
 */
@Service
public class FileInfoServiceImpl implements IFileInfoService
{
    @Autowired
    private FileInfoMapper fileInfoMapper;

    /**
     * 查询文件信息
     * 
     * @param fileId 文件信息主键
     * @return 文件信息
     */
    @Override
    public FileInfoVo selectFileInfoByFileId(Long fileId)
    {
        FileInfoVo fileInfoVo = new FileInfoVo();
        try {
            FileInfo fileInfo = fileInfoMapper.selectFileInfoByFileId(fileId);
            BeanUtils.copyProperties(fileInfo, fileInfoVo);
            List<String> fileNames = new ArrayList<>();
            if(!StringUtils.isEmpty(fileInfo.getFilePath())){
                //读取指定路径的所有文件
                String filePath = DUPTConfig.getUploadPath() + fileInfo.getFilePath();
                Path startPath = Paths.get(filePath);
                if(Files.exists(startPath)){
                    //递归遍历所有文件
                    Files.walk(startPath)
                            .filter(Files::isRegularFile)
                            .map(startPath::relativize)  // 获取相对路径
                            .map(Path::toString)
                            .forEach(fileNames::add);
                    fileInfoVo.setFileNameList(fileNames);
                }
            }
        }catch (Exception e){
            throw new RuntimeException("递归遍历目录失败 ", e);
        }
        return fileInfoVo;
    }

    /**
     * 查询文件信息列表
     * 
     * @param fileInfo 文件信息
     * @return 文件信息
     */
    @Override
    public List<FileInfoVo> selectFileInfoList(FileInfo fileInfo)
    {
        List<FileInfo> fileInfoList = fileInfoMapper.selectFileInfoList(fileInfo);
        List<FileInfoVo> fileInfoVoList = JSON.parseArray(JSON.toJSONString(fileInfoList), FileInfoVo.class);
        for(FileInfoVo fileInfoVo: fileInfoVoList){
            List<String> fileNames = new ArrayList<>();
            try {
                if(!StringUtils.isEmpty(fileInfoVo.getFilePath())){
                    //读取指定路径的所有文件
                    String filePath = DUPTConfig.getUploadPath() + fileInfoVo.getFilePath();
                    Path startPath = Paths.get(filePath);
                    if(Files.exists(startPath)){
                        //递归遍历所有文件
                        Files.walk(startPath)
                                .filter(Files::isRegularFile)
                                .map(startPath::relativize)  // 获取相对路径
                                .map(Path::toString)
                                .forEach(fileNames::add);
                        fileInfoVo.setFileNameList(fileNames);
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException("递归遍历目录失败 ", e);
            }
        }
        return fileInfoVoList;
    }

    /**
     * 新增文件信息
     * 
     * @param fileInfoVo 文件信息
     * @param files 文件
     * @return 结果
     */
    @Override
    public int insertFileInfo(String fileInfoVo, List<MultipartFile> files) throws IOException {
        //1.保存质量追溯信息
        FileInfo fileInfo = JSON.parseObject(fileInfoVo, FileInfo.class);
        //2.保存文件到服务器
        // 上传文件路径
        String filePath = DUPTConfig.getUploadPath();
        if(files!=null){
            for (MultipartFile file : files) {
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                // 确保数据库存储的是相对路径（不带profile/upload）
                if (fileName.startsWith("/profile/upload/")) {
                    // 找到最后一个斜杠的位置
                    int lastSlashIndex = fileName.lastIndexOf('/');
                    // 找到倒数第二个斜杠的位置
                    int secondLastSlashIndex = fileName.lastIndexOf('/', lastSlashIndex - 1);
                    // 截取两个斜杠之间的内容（包含斜杠）
                    fileName = fileName.substring(secondLastSlashIndex, lastSlashIndex + 1);
                }
                fileInfo.setFilePath(fileName);
            }
        }
        fileInfo.setFileStatus("1");
        fileInfo.setCreateTime(DateUtils.getNowDate());
        fileInfo.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        return fileInfoMapper.insertFileInfo(fileInfo);
    }

    /**
     * 修改文件信息
     * 
     * @param fileInfoVo 文件信息
     * @param files 文件
     * @return 结果
     */
    @Override
    public int updateFileInfo(String fileInfoVo, List<MultipartFile> files) throws IOException {
        //1.保存质量追溯信息
        FileInfoVo fileVo = JSON.parseObject(fileInfoVo, FileInfoVo.class);
        FileInfo fileInfo = fileInfoMapper.selectFileInfoByFileId(fileVo.getFileId());
        fileInfo.setFileStatus(fileVo.getFileStatus());
        fileInfo.setFileType(fileVo.getFileType());
        // 上传文件路径
        String filePath = DUPTConfig.getUploadPath();
        //2.查询原有的所有文件，根据传来的文件作对比，删除不存在的文件
        List<String> fileNames = new ArrayList<>();
        try {
            if(!StringUtils.isEmpty(fileInfo.getFilePath())){
                //读取指定路径的所有文件
                Path startPath = Paths.get(filePath+fileInfo.getFilePath());
                if(Files.notExists(startPath)){
                    Files.createDirectory(startPath);
                }
                //递归遍历所有文件
                Files.walk(startPath)
                        .filter(Files::isRegularFile)
                        .map(startPath::relativize)  // 获取相对路径
                        .map(Path::toString)
                        .forEach(fileNames::add);
            }
        } catch (IOException e) {
            throw new RuntimeException("递归遍历目录失败 ", e);
        }
        for(String fileName: fileNames){
            if(!fileVo.getFileNameList().contains(fileName)){
                FileUtils.deleteFile(filePath+ fileInfo.getFilePath()+ fileName);
            }
        }

        //3.保存文件到服务器指定的文件夹中
        for (MultipartFile file : files) {
            if(StringUtils.isNotEmpty(fileInfo.getFilePath())){
                FileUtils.uploadFile(file,filePath+fileInfo.getFilePath());
            }else{
                //String originalFilename = file.getOriginalFilename();
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                // 确保数据库存储的是相对路径（不带profile/upload）
                if (fileName.startsWith("/profile/upload/")) {
                    // 找到最后一个斜杠的位置
                    int lastSlashIndex = fileName.lastIndexOf('/');
                    // 找到倒数第二个斜杠的位置
                    int secondLastSlashIndex = fileName.lastIndexOf('/', lastSlashIndex - 1);

                    // 截取两个斜杠之间的内容（包含斜杠）
                    fileName = fileName.substring(secondLastSlashIndex, lastSlashIndex + 1);
                }
                fileInfo.setFilePath(fileName);
            }
        }
        fileInfo.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        fileInfo.setUpdateTime(DateUtils.getNowDate());
        return fileInfoMapper.updateFileInfo(fileInfo);
    }

    /**
     * 批量删除文件信息
     * 
     * @param fileIds 需要删除的文件信息主键
     * @return 结果
     */
    @Override
    public int deleteFileInfoByFileIds(Long[] fileIds)
    {
        return fileInfoMapper.deleteFileInfoByFileIds(fileIds);
    }

    /**
     * 删除文件信息信息
     * 
     * @param fileId 文件信息主键
     * @return 结果
     */
    @Override
    public int deleteFileInfoByFileId(Long fileId)
    {
        return fileInfoMapper.deleteFileInfoByFileId(fileId);
    }

    @Override
    public FileInfoVo selectFileInfoByFileInfoId(Long fileInfoId) {
        FileInfoVo fileInfoVo = new FileInfoVo();
        try {
            FileInfo fileInfo = fileInfoMapper.selectFileInfoByFileId(fileInfoId);
            BeanUtils.copyProperties(fileInfo, fileInfoVo);
            List<String> fileNames = new ArrayList<>();
            if(!StringUtils.isEmpty(fileInfo.getFilePath())){
                //读取指定路径的所有文件
                String filePath = DUPTConfig.getUploadPath() + fileInfo.getFilePath();
                Path startPath = Paths.get(filePath);
                if(Files.exists(startPath)){
                    //递归遍历所有文件
                    Files.walk(startPath)
                            .filter(Files::isRegularFile)
                            .map(startPath::relativize)  // 获取相对路径
                            .map(Path::toString)
                            .forEach(fileNames::add);
                    fileInfoVo.setFileNameList(fileNames);
                }
            }
        }catch (Exception e){
            throw new RuntimeException("递归遍历目录失败 ", e);
        }
        return fileInfoVo;
    }
}
